package cn.turboinfo.fuyang.api.domain.mini.usecase.index;

import cn.turboinfo.fuyang.api.domain.common.handler.product.ProductDataFactory;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService;
import cn.turboinfo.fuyang.api.domain.common.service.shop.HousekeepingShopService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.Product;
import cn.turboinfo.fuyang.api.entity.common.pojo.shop.HousekeepingShop;
import cn.turboinfo.fuyang.api.entity.mini.fo.index.MiniIndexNearbyProduct;
import kotlin.Pair;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 列表首页附近服务
 *
 * @author sunshow
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniIndexListNearbyProductUseCase extends AbstractUseCase<MiniIndexListNearbyProductUseCase.InputData, MiniIndexListNearbyProductUseCase.OutputData> {

    private final HousekeepingShopService housekeepingShopService;
    private final ProductDataFactory productDataFactory;

    private final ProductService productService;

    @Override
    protected OutputData doAction(InputData inputData) {
        BigDecimal longitude = inputData.getLongitude();
        BigDecimal latitude = inputData.getLatitude();

        List<HousekeepingShop> shopList = new ArrayList<>();

        // 距离
        Map<Long, BigDecimal> shopIdDistanceMap;

        if (longitude != null && latitude != null) {
            // 获取距离10公里内最近的20家门店
            List<Pair<HousekeepingShop, BigDecimal>> pairList = housekeepingShopService.findByGeoRadius(longitude, latitude, 10D, 20L);
            shopList = pairList.stream()
                    .map(Pair::getFirst)
                    .collect(Collectors.toList());
            shopIdDistanceMap = pairList.stream()
                    .collect(
                            Collectors.toMap(
                                    pair -> pair.getFirst().getId(),
                                    Pair::getSecond
                            )
                    );
        } else {
            shopIdDistanceMap = new HashMap<>();
        }

        // 如何门店列表是空 则不按地区去查询
        if (shopList.isEmpty()) {
            // 否则取评分最高的20家门店
            shopList = housekeepingShopService.findTopByCreditScore(20);
        }

        // 根据门店取对应产品
        Set<Long> shopIdSet = shopList.stream()
                .map(HousekeepingShop::getId)
                .collect(Collectors.toSet());
        // TODO 这里简单粗暴全部查出来分组取了 量大需要优化
        List<Product> productList = productService.findByShopIdCollection(shopIdSet);

        // 拼装企业信息
        productDataFactory.assembleCompany(productList);

        // 拼装附件信息
        productDataFactory.assembleAttachment(productList);

        Map<Long, List<Product>> shopIdProductListMap = productList.stream()
                .collect(
                        Collectors.groupingBy(
                                Product::getShopId,
                                Collectors.toList()
                        )
                );

        // 组装返回数据
        List<MiniIndexNearbyProduct> nearbyProductList = shopList.stream()
                .filter(shop -> shopIdProductListMap.containsKey(shop.getId()))
                .map(shop -> {
                    List<Product> _productList = shopIdProductListMap.get(shop.getId());
                    MiniIndexNearbyProduct nearbyProduct = new MiniIndexNearbyProduct();
                    nearbyProduct.setProduct(_productList.get(0));
                    nearbyProduct.setDistance(shopIdDistanceMap.get(shop.getId()));
                    return nearbyProduct;
                })
                .limit(10)
                .toList();

        return OutputData.builder()
                .nearbyProductList(nearbyProductList)
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        /**
         * 经度
         */
        private BigDecimal longitude;

        /**
         * 纬度
         */
        private BigDecimal latitude;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        /**
         * 附近服务列表
         */
        private List<MiniIndexNearbyProduct> nearbyProductList;

    }
}
